use std::collections::VecDeque;
use std::sync::Arc;

use bytes::Bytes;

use crate::config::http::core_conf::HttpCoreRuntimeConf;
use crate::error::*;
use crate::http::base::conn::BoxHttpConn;
use crate::http::base::headers::HttpHeaders;
use crate::http::base::parse::HttpResult;
use crate::http::base::{Request, Response};
use crate::http::v1::client_session::ClientSession as ClientSessionV1;
use crate::http::v1::server_session::ServerSession as ServerSessionV1;
use crate::http::v2::server_session::ServerSession as ServerSessionV2;

#[allow(dead_code)]
pub enum ServerSession {
    H1(ServerSessionV1),
    H2(ServerSessionV2),
}

#[allow(dead_code)]
impl ServerSession {
    pub fn new_http1(hc: BoxHttpConn) -> Self {
        Self::H1(ServerSessionV1::new(hc))
    }

    pub fn new_http2(hc: BoxHttpConn) -> Self {
        Self::H2(ServerSessionV2::new(hc))
    }

    pub fn get_hc(&mut self) -> &mut BoxHttpConn {
        match self {
            ServerSession::H1(s1) => s1.get_hc(),
            ServerSession::H2(s2) => s2.get_hc(),
        }
    }

    // 读取完请求头后返回.
    // 该方法有三种返回值:
    // - Ok(Some(req)): 成功读取到header.
    // - Ok(None): 连接断开、超时等场景中未能读取到任何数据, 此时建议proxy直接关闭连接即可.
    // - Err(err): 读取数据或解析数据发生错误. 此时proxy应该响应4xx给客户端.
    pub async fn read_request(&mut self) -> Result<Option<&mut Request>> {
        match self {
            Self::H1(s1) => s1.read_request().await,

            // 始终返回Ok(true).
            // 对于H2来说,此时应该读取到了request header.
            Self::H2(s2) => s2.read_request(),
        }
    }

    pub fn request(&mut self) -> &mut Request {
        match self {
            ServerSession::H1(s1) => s1.request(),
            ServerSession::H2(s2) => s2.request(),
        }
    }

    pub async fn read_request_body(
        &mut self,
        bufs: &mut VecDeque<Bytes>,
    ) -> Result<HttpResult> {
        match self {
            ServerSession::H1(s1) => s1.read_request_body(bufs).await,
            ServerSession::H2(s2) => s2.read_request_body(bufs).await,
        }
    }

    pub fn expect_trailers_num(&self) -> usize {
        match self {
            ServerSession::H1(s1) => s1.expect_trailers_num(),
            ServerSession::H2(s2) => s2.expect_trailers_num(),
        }
    }

    pub fn get_req_trailer_headers(&self) -> Result<Option<&HttpHeaders>> {
        match self {
            ServerSession::H1(s1) => s1.get_req_trailer_headers(),
            ServerSession::H2(s2) => s2.get_req_trailer_headers(),
        }
    }

    pub async fn send_resp_header(
        &mut self,
        resp: &mut Response,
    ) -> Result<()> {
        match self {
            ServerSession::H1(s1) => s1.send_resp_header(resp).await,
            ServerSession::H2(s2) => s2.send_resp_header(resp).await,
        }
    }

    pub async fn write_resp_body(
        &mut self,
        bufs: &mut VecDeque<Bytes>,
        done: bool,
    ) -> Result<HttpResult> {
        match self {
            ServerSession::H1(s1) => s1.write_resp_body(bufs, done).await,
            ServerSession::H2(s2) => s2.write_resp_body(bufs, done).await,
        }
    }

    pub fn expect_write_trailers_num(&mut self) -> usize {
        match self {
            ServerSession::H1(s1) => s1.expect_write_trailers_num(),
            ServerSession::H2(s2) => s2.expect_write_trailers_num(),
        }
    }

    pub async fn write_resp_trailers(
        &mut self,
        headers: &HttpHeaders,
    ) -> Result<()> {
        match self {
            ServerSession::H1(s1) => s1.write_resp_trailers(headers).await,
            ServerSession::H2(s2) => s2.write_resp_trailers(headers).await,
        }
    }

    pub fn header_send(&self) -> bool {
        match self {
            ServerSession::H1(s1) => s1.header_send,
            ServerSession::H2(s2) => s2.header_send,
        }
    }

    pub fn write_resp_done(&self) -> bool {
        match self {
            ServerSession::H1(s1) => s1.write_resp_done(),
            ServerSession::H2(s2) => s2.write_resp_done(),
        }
    }

    pub async fn finalize(&mut self, abort: bool) {
        match self {
            ServerSession::H1(s1) => s1.finalize(abort).await,
            ServerSession::H2(s2) => s2.finalize(abort).await,
        }
    }

    pub fn release(self) -> Option<BoxHttpConn> {
        match self {
            ServerSession::H1(s1) => s1.release(),
            ServerSession::H2(_) => None,
        }
    }
}

#[allow(dead_code)]
pub enum ClientSession {
    H1(ClientSessionV1),
    H2(i32),
}

#[allow(dead_code)]
impl ClientSession {
    pub fn new_http1(
        hc: BoxHttpConn,
        conf: Option<Arc<HttpCoreRuntimeConf>>,
    ) -> Self {
        Self::H1(ClientSessionV1::new(hc, conf))
    }

    pub fn new_http2(
        hc: BoxHttpConn,
        conf: Option<Arc<HttpCoreRuntimeConf>>,
    ) -> Self {
        _ = hc;
        _ = conf;
        todo!()
    }

    pub async fn send_req_header(&mut self, req: &mut Request) -> Result<()> {
        match self {
            ClientSession::H1(c1) => c1.send_req_header(req).await,
            ClientSession::H2(_) => todo!(),
        }
    }

    pub async fn write_req_body(
        &mut self,
        bufs: &mut VecDeque<Bytes>,
        done: bool,
    ) -> Result<HttpResult> {
        match self {
            ClientSession::H1(c1) => c1.write_req_body(bufs, done).await,
            ClientSession::H2(_) => todo!(),
        }
    }

    pub fn expect_write_trailers_num(&mut self) -> usize {
        match self {
            ClientSession::H1(s1) => s1.expect_write_trailers_num(),
            ClientSession::H2(_) => todo!(),
        }
    }

    pub async fn write_req_trailers(
        &mut self,
        headers: &HttpHeaders,
    ) -> Result<()> {
        match self {
            ClientSession::H1(c1) => c1.write_req_trailers(headers).await,
            ClientSession::H2(_) => todo!(),
        }
    }

    pub fn header_send(&self) -> bool {
        match self {
            ClientSession::H1(c1) => c1.header_send,
            ClientSession::H2(_) => todo!(),
        }
    }

    pub fn write_request_done(&self) -> bool {
        match self {
            ClientSession::H1(c1) => c1.write_request_done(),
            ClientSession::H2(_) => todo!(),
        }
    }

    pub async fn read_response(&mut self) -> Result<&mut Response> {
        match self {
            ClientSession::H1(c1) => c1.read_response().await,
            ClientSession::H2(_) => todo!(),
        }
    }

    pub async fn read_resp_body(
        &mut self,
        bufs: &mut VecDeque<Bytes>,
    ) -> Result<HttpResult> {
        match self {
            ClientSession::H1(c1) => c1.read_resp_body(bufs).await,
            ClientSession::H2(_) => todo!(),
        }
    }

    pub fn expect_trailers_num(&self) -> usize {
        match self {
            ClientSession::H1(c1) => c1.expect_trailers_num(),
            ClientSession::H2(_) => todo!(),
        }
    }

    pub fn get_resp_trailer_headers(&self) -> Result<Option<&HttpHeaders>> {
        match self {
            ClientSession::H1(c1) => c1.get_resp_trailer_headers(),
            ClientSession::H2(_) => todo!(),
        }
    }

    pub async fn finalize(&mut self, abort: bool) {
        match self {
            ClientSession::H1(c1) => c1.finalize(abort).await,
            ClientSession::H2(_) => todo!(),
        }
    }

    pub fn release(self) -> Option<BoxHttpConn> {
        match self {
            ClientSession::H1(c1) => c1.release(),
            ClientSession::H2(_) => todo!(),
        }
    }
}
